/*
* Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2006, Keir Fraser, XenSource Inc.
*
* This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
+ * under the terms and conditions of the GNU General Public License, version
+ * 2, as published by the Free Software Foundation.
*
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
- *
*/
#include "acpi2_0.h"
+#include "../config.h"
+#include "../util.h"
extern struct acpi_20_rsdp Rsdp;
extern struct acpi_20_rsdt Rsdt;
extern struct acpi_20_xsdt Xsdt;
extern struct acpi_20_fadt Fadt;
-extern struct acpi_20_madt Madt;
extern struct acpi_20_facs Facs;
-extern unsigned char *AmlCode;
+extern unsigned char AmlCode[];
extern int DsdtLen;
+static void set_checksum(
+ void *table, uint32_t checksum_offset, uint32_t length)
+{
+ uint8_t *p, sum = 0;
-typedef struct _ACPI_TABLE_ALL{
- struct acpi_20_rsdp *Rsdp;
- struct acpi_20_rsdt *Rsdt;
- struct acpi_20_xsdt *Xsdt;
- struct acpi_20_fadt *Fadt;
- struct acpi_20_madt *Madt;
- struct acpi_20_facs *Facs;
- unsigned char *Dsdt;
- uint32_t RsdpOffset;
- uint32_t RsdtOffset;
- uint32_t XsdtOffset;
- uint32_t FadtOffset;
- uint32_t MadtOffset;
- uint32_t FacsOffset;
- uint32_t DsdtOffset;
-}ACPI_TABLE_ALL;
-
-static
-void
-MemCopy(void* src, void* dst, int len){
-
- uint8_t* src0=src;
- uint8_t* dst0=dst;
-
- while(len--){
- *(dst0++)=*(src0++);
- }
+ p = table;
+ p[checksum_offset] = 0;
+
+ while ( length-- )
+ sum = sum + *p++;
+
+ p = table;
+ p[checksum_offset] = -sum;
}
-static
-void
-SetCheckSum(
- void* Table,
- uint32_t ChecksumOffset,
- uint32_t Length
- )
-/*
- * Routine Description:
- * Calculate Checksum and store the result in the checksum
- * filed of the table
- *
- * INPUT:
- * Table: Start pointer of table
- * ChecksumOffset: Offset of checksum field in the table
- * Length: Length of Table
- */
+int construct_madt(struct acpi_20_madt *madt)
{
- uint8_t Sum = 0;
- uint8_t *Ptr;
+ struct acpi_20_madt_intsrcovr *intsrcovr;
+ struct acpi_20_madt_ioapic *io_apic;
+ struct acpi_20_madt_lapic *lapic;
+ int i, offset = 0;
+
+ memset(madt, 0, sizeof(*madt));
+ madt->header.signature = ACPI_2_0_MADT_SIGNATURE;
+ madt->header.revision = ACPI_2_0_MADT_REVISION;
+ strncpy(madt->header.oem_id, "INTEL ", 6);
+ madt->header.oem_table_id = ACPI_OEM_TABLE_ID;
+ madt->header.oem_revision = ACPI_OEM_REVISION;
+ madt->header.creator_id = ACPI_CREATOR_ID;
+ madt->header.creator_revision = ACPI_CREATOR_REVISION;
+ madt->lapic_addr = LAPIC_BASE_ADDRESS;
+ madt->flags = ACPI_PCAT_COMPAT;
+ offset += sizeof(*madt);
+
+ intsrcovr = (struct acpi_20_madt_intsrcovr *)(madt + 1);
+ for ( i = 0; i < 16; i++ )
+ {
+ if ( !(PCI_ISA_IRQ_MASK & (1U << i)) )
+ continue;
+
+ /* PCI: active-low level-triggered */
+ memset(intsrcovr, 0, sizeof(*intsrcovr));
+ intsrcovr->type = ACPI_INTERRUPT_SOURCE_OVERRIDE;
+ intsrcovr->length = sizeof(*intsrcovr);
+ intsrcovr->source = i;
+ intsrcovr->gsi = i;
+ intsrcovr->flags = 0xf;
+
+ offset += sizeof(*intsrcovr);
+ intsrcovr++;
+ }
- Ptr=Table;
- Ptr[ChecksumOffset]=0;
- while (Length--) {
- Sum = (uint8_t)(Sum + (*Ptr++));
+ io_apic = (struct acpi_20_madt_ioapic *)intsrcovr;
+ memset(io_apic, 0, sizeof(*io_apic));
+ io_apic->type = ACPI_IO_APIC;
+ io_apic->length = sizeof(*io_apic);
+ io_apic->ioapic_id = IOAPIC_ID;
+ io_apic->ioapic_addr = IOAPIC_BASE_ADDRESS;
+ offset += sizeof(*io_apic);
+
+ lapic = (struct acpi_20_madt_lapic *)io_apic;
+ for ( i = 0; i < get_vcpu_nr(); i++ )
+ {
+ memset(lapic, 0, sizeof(*lapic));
+ lapic->type = ACPI_PROCESSOR_LOCAL_APIC;
+ lapic->length = sizeof(*lapic);
+ lapic->acpi_processor_id = i;
+ lapic->apic_id = i;
+ lapic->flags = ACPI_LOCAL_APIC_ENABLED;
+ offset += sizeof(*lapic);
+ lapic++;
}
-
- Ptr = Table;
- Ptr[ChecksumOffset] = (uint8_t) (0xff - Sum + 1);
-}
-//
-// FIELD_OFFSET - returns the byte offset to a field within a structure
-//
-#define FIELD_OFFSET(TYPE,Field) ((uint32_t)(&(((TYPE *) 0)->Field)))
+ madt->header.length = offset;
+ set_checksum(madt, offsetof(struct acpi_header, checksum), offset);
-static
-void
-UpdateTable(
- ACPI_TABLE_ALL *table
- )
-/*
- * Update the ACPI table:
- * fill in the actuall physical address of RSDT, XSDT, FADT, MADT, FACS
- * Caculate the checksum
- */
-{
- // RSDP Update
- table->Rsdp->rsdt_address = (uint32_t)(ACPI_PHYSICAL_ADDRESS+
- table->RsdtOffset);
- table->Rsdp->xsdt_address = (uint64_t)(ACPI_PHYSICAL_ADDRESS+
- table->XsdtOffset);
- SetCheckSum(table->Rsdp,
- FIELD_OFFSET(struct acpi_10_rsdp, checksum),
- sizeof(struct acpi_10_rsdp)
- );
- SetCheckSum(table->Rsdp,
- FIELD_OFFSET(struct acpi_20_rsdp,
- extended_checksum),
- sizeof(struct acpi_20_rsdp)
- );
-
-
- //RSDT Update
- table->Rsdt->entry[0] = (uint32_t)(ACPI_PHYSICAL_ADDRESS +
- table->FadtOffset);
- table->Rsdt->entry[1] = (uint32_t)(ACPI_PHYSICAL_ADDRESS +
- table->MadtOffset);
- table->Rsdt->header.length = sizeof (struct acpi_header) +
- 2*sizeof(uint32_t);
- SetCheckSum(table->Rsdt,
- FIELD_OFFSET(struct acpi_header, checksum),
- table->Rsdt->header.length
- );
-
- //XSDT Update
- table->Xsdt->entry[0] = (uint64_t)(ACPI_PHYSICAL_ADDRESS +
- table->FadtOffset);
- table->Xsdt->entry[1] = (uint64_t)(ACPI_PHYSICAL_ADDRESS +
- table->MadtOffset);
- table->Xsdt->header.length = sizeof (struct acpi_header) +
- 2*sizeof(uint64_t);
- SetCheckSum(table->Xsdt,
- FIELD_OFFSET(struct acpi_header, checksum),
- table->Xsdt->header.length
- );
-
- // FADT Update
- table->Fadt->dsdt = (uint32_t)(ACPI_PHYSICAL_ADDRESS +
- table->DsdtOffset);
- table->Fadt->x_dsdt = (uint64_t)(ACPI_PHYSICAL_ADDRESS +
- table->DsdtOffset);
- table->Fadt->firmware_ctrl = (uint32_t)(ACPI_PHYSICAL_ADDRESS +
- table->FacsOffset);
- table->Fadt->x_firmware_ctrl = (uint64_t)(ACPI_PHYSICAL_ADDRESS +
- table->FacsOffset);
- SetCheckSum(table->Fadt,
- FIELD_OFFSET(struct acpi_header, checksum),
- sizeof(struct acpi_20_fadt)
- );
-
- // MADT update
- SetCheckSum(table->Madt,
- FIELD_OFFSET(struct acpi_header, checksum),
- sizeof(struct acpi_20_madt)
- );
+ return offset;
}
-void
-AcpiBuildTable(uint8_t* buf)
/*
- * Copy all the ACPI table to buffer
- * Buffer Layout:
- * FACS
- * RSDP
- * RSDT
- * XSDT
- * FADT
- * MADT
- * DSDT
- *
- */
+ * Copy all the ACPI table to buffer.
+ * Buffer layout: FACS, DSDT, FADT, MADT, XSDT, RSDT, RSDP.
+ */
+int acpi_build_tables(uint8_t *buf)
{
- ACPI_TABLE_ALL table;
- int offset=0;
-
- // FACS: should be 64-bit alignment
- // so it is put at the start of buffer
- // as the buffer is 64 bit alignment
- table.FacsOffset = offset;
- table.Facs = (struct acpi_20_facs *)(&buf[offset]);
- MemCopy(&Facs, table.Facs, sizeof(struct acpi_20_facs));
- offset += sizeof(struct acpi_20_facs);
-
- // RSDP
- table.RsdpOffset = offset;
- table.Rsdp = (struct acpi_20_rsdp *)(&buf[offset]);
- MemCopy(&Rsdp, table.Rsdp, sizeof(struct acpi_20_rsdp));
- offset += sizeof(struct acpi_20_rsdp);
-
- // RSDT
- table.RsdtOffset = offset;
- table.Rsdt = (struct acpi_20_rsdt *)(&buf[offset]);
- MemCopy(&Rsdt, table.Rsdt, sizeof(struct acpi_20_rsdt));
- offset += sizeof(struct acpi_20_rsdt);
-
- // XSDT
- table.XsdtOffset = offset;
- table.Xsdt = (struct acpi_20_xsdt *)(&buf[offset]);
- MemCopy(&Xsdt, table.Xsdt, sizeof(struct acpi_20_xsdt));
- offset += sizeof(struct acpi_20_xsdt);
-
- // FADT
- table.FadtOffset = offset;
- table.Fadt = (struct acpi_20_fadt *)(&buf[offset]);
- MemCopy(&Fadt, table.Fadt, sizeof(struct acpi_20_fadt));
- offset += sizeof(struct acpi_20_fadt);
-
- // MADT
- table.MadtOffset = offset;
- table.Madt = (struct acpi_20_madt*)(&buf[offset]);
- MemCopy(&Madt, table.Madt, sizeof(struct acpi_20_madt));
- offset += sizeof(struct acpi_20_madt);
-
- // DSDT
- table.DsdtOffset = offset;
- table.Dsdt = (unsigned char *)(&buf[offset]);
- MemCopy(&AmlCode, table.Dsdt, DsdtLen);
- offset += DsdtLen;
-
- UpdateTable(&table);
+ struct acpi_20_rsdp *rsdp;
+ struct acpi_20_rsdt *rsdt;
+ struct acpi_20_xsdt *xsdt;
+ struct acpi_20_fadt *fadt;
+ struct acpi_20_madt *madt = 0;
+ struct acpi_20_facs *facs;
+ unsigned char *dsdt;
+ int offset = 0, nr_vcpus = get_vcpu_nr();
+
+#define inc_offset(sz) (offset = (offset + (sz) + 15) & ~15)
+#define requires_madt() (nr_vcpus > 1)
+
+ facs = (struct acpi_20_facs *)&buf[offset];
+ memcpy(facs, &Facs, sizeof(struct acpi_20_facs));
+ inc_offset(sizeof(struct acpi_20_facs));
+
+ dsdt = (unsigned char *)&buf[offset];
+ memcpy(dsdt, &AmlCode, DsdtLen);
+ inc_offset(DsdtLen);
+
+ fadt = (struct acpi_20_fadt *)&buf[offset];
+ memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt));
+ inc_offset(sizeof(struct acpi_20_fadt));
+ fadt->dsdt = (unsigned long)dsdt;
+ fadt->x_dsdt = (unsigned long)dsdt;
+ fadt->firmware_ctrl = (unsigned long)facs;
+ fadt->x_firmware_ctrl = (unsigned long)facs;
+ set_checksum(fadt,
+ offsetof(struct acpi_header, checksum),
+ sizeof(struct acpi_20_fadt));
+
+ if ( requires_madt() )
+ {
+ madt = (struct acpi_20_madt *)&buf[offset];
+ inc_offset(construct_madt(madt));
+ }
+
+ xsdt = (struct acpi_20_xsdt *)&buf[offset];
+ memcpy(xsdt, &Xsdt, sizeof(struct acpi_20_xsdt));
+ inc_offset(sizeof(struct acpi_20_xsdt));
+ xsdt->entry[0] = (unsigned long)fadt;
+ xsdt->header.length = sizeof(struct acpi_header) + sizeof(uint64_t);
+ if ( requires_madt() )
+ {
+ xsdt->entry[1] = (unsigned long)madt;
+ xsdt->header.length += sizeof(uint64_t);
+ }
+ set_checksum(xsdt,
+ offsetof(struct acpi_header, checksum),
+ xsdt->header.length);
+
+ rsdt = (struct acpi_20_rsdt *)&buf[offset];
+ memcpy(rsdt, &Rsdt, sizeof(struct acpi_20_rsdt));
+ inc_offset(sizeof(struct acpi_20_rsdt));
+ rsdt->entry[0] = (unsigned long)fadt;
+ rsdt->header.length = sizeof(struct acpi_header) + sizeof(uint32_t);
+ if ( requires_madt() )
+ {
+ rsdt->entry[1] = (unsigned long)madt;
+ rsdt->header.length += sizeof(uint32_t);
+ }
+ set_checksum(rsdt,
+ offsetof(struct acpi_header, checksum),
+ rsdt->header.length);
+
+ rsdp = (struct acpi_20_rsdp *)&buf[offset];
+ memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp));
+ inc_offset(sizeof(struct acpi_20_rsdp));
+ rsdp->rsdt_address = (unsigned long)rsdt;
+ rsdp->xsdt_address = (unsigned long)xsdt;
+ set_checksum(rsdp,
+ offsetof(struct acpi_10_rsdp, checksum),
+ sizeof(struct acpi_10_rsdp));
+ set_checksum(rsdp,
+ offsetof(struct acpi_20_rsdp, extended_checksum),
+ sizeof(struct acpi_20_rsdp));
+
+ return offset;
}
/*
+++ /dev/null
-/*
- * acpi_madt.c: Update ACPI MADT table for multiple processor guest.
- *
- * Yu Ke, ke.yu@intel.com
- * Copyright (c) 2005, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "acpi/acpi2_0.h"
-#include "util.h"
-#include "acpi_utils.h"
-#include <xen/hvm/hvm_info_table.h>
-
-#define NULL ((void*)0)
-
-static struct hvm_info_table *table = NULL;
-
-static int validate_hvm_info(struct hvm_info_table *t)
-{
- char signature[] = "HVM INFO";
- uint8_t *ptr = (uint8_t *)t;
- uint8_t sum = 0;
- int i;
-
- /* strncmp(t->signature, "HVM INFO", 8) */
- for ( i = 0; i < 8; i++ )
- {
- if ( signature[i] != t->signature[i] )
- {
- printf("Bad hvm info signature\n");
- return 0;
- }
- }
-
- for ( i = 0; i < t->length; i++ )
- sum += ptr[i];
-
- return (sum == 0);
-}
-
-/* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */
-struct hvm_info_table *get_hvm_info_table(void)
-{
- struct hvm_info_table *t;
-
- if ( table != NULL )
- return table;
-
- t = (struct hvm_info_table *)HVM_INFO_PADDR;
-
- if ( !validate_hvm_info(t) )
- {
- printf("Bad hvm info table\n");
- return NULL;
- }
-
- table = t;
-
- return table;
-}
-
-int get_vcpu_nr(void)
-{
- struct hvm_info_table *t = get_hvm_info_table();
- return (t ? t->nr_vcpus : 1); /* default 1 vcpu */
-}
-
-int get_acpi_enabled(void)
-{
- struct hvm_info_table *t = get_hvm_info_table();
- return (t ? t->acpi_enabled : 0); /* default no acpi */
-}
-
-
-static void *
-acpi_madt_get_madt(unsigned char *acpi_start)
-{
- struct acpi_20_rsdt *rsdt;
- struct acpi_20_madt *madt;
-
- rsdt = acpi_rsdt_get(acpi_start);
- if ( rsdt == NULL )
- return NULL;
-
- madt = (struct acpi_20_madt *)(acpi_start + rsdt->entry[1] -
- ACPI_PHYSICAL_ADDRESS);
- if ( madt->header.header.signature != ACPI_2_0_MADT_SIGNATURE )
- {
- printf("Bad MADT signature \n");
- return NULL;
- }
-
- return madt;
-}
-
-static int
-acpi_madt_set_local_apics(
- int nr_vcpu,
- struct acpi_20_madt *madt)
-{
- int i;
-
- if ( (nr_vcpu > MAX_VIRT_CPUS) || (nr_vcpu < 0) || !madt )
- return -1;
-
- for ( i = 0; i < nr_vcpu; i++ )
- {
- madt->lapic[i].type = ACPI_PROCESSOR_LOCAL_APIC;
- madt->lapic[i].length = sizeof(struct acpi_20_madt_lapic);
- madt->lapic[i].acpi_processor_id = i;
- madt->lapic[i].apic_id = i;
- madt->lapic[i].flags = 1;
- }
-
- madt->header.header.length =
- sizeof(struct acpi_20_madt) -
- (MAX_VIRT_CPUS - nr_vcpu) * sizeof(struct acpi_20_madt_lapic);
-
- return 0;
-}
-
-#define FIELD_OFFSET(TYPE,Field) ((unsigned int)(&(((TYPE *) 0)->Field)))
-
-int acpi_madt_update(unsigned char *acpi_start)
-{
- int rc;
- struct acpi_20_madt *madt;
-
- madt = acpi_madt_get_madt(acpi_start);
- if ( !madt )
- return -1;
-
- rc = acpi_madt_set_local_apics(get_vcpu_nr(), madt);
- if ( rc != 0 )
- return rc;
-
- set_checksum(
- madt, FIELD_OFFSET(struct acpi_header, checksum),
- madt->header.header.length);
-
- return 0;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */